﻿using System.Linq.Expressions;
using Mapster;
using Microsoft.EntityFrameworkCore;

namespace Devonline.AspNetCore;

/// <summary>
/// 公共数据处理服务
/// </summary>
/// <typeparam name="TDbContext">数据库上下文</typeparam>
/// <typeparam name="TEntitySet">业务数据类型</typeparam>
/// <typeparam name="TKey">键类型</typeparam>
public interface IDataService<TDbContext, TEntitySet, TKey> :
    IServiceBase<TDbContext, TKey>
    where TDbContext : DbContext
    where TEntitySet : class, IEntitySet<TKey>
    where TKey : IConvertible
{
    #region 数据查询方法
    /// <summary>
    /// 统一数据源查询入口, 可缓存数据源, 仅返回当前类型引用
    /// </summary>
    /// <returns></returns>
    IQueryable<TEntitySet> GetQueryable();
    /// <summary>
    /// 统一数据源查询入口, 可缓存数据源, 仅返回当前类型引用
    /// </summary>
    /// <param name="predicate">过滤条件</param>
    /// <returns></returns>
    IQueryable<TEntitySet> GetQueryable(Expression<Func<TEntitySet, bool>> predicate);
    /// <summary>
    /// 根据 id 获取对象
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    Task<TEntitySet?> GetAsync(TKey id);
    /// <summary>
    /// 从 QueryOptions 和上下文自动获取查询表达式的内容并执行查询返回分页的结果
    /// 暂不支持 orderby, select 和 expand 表达式
    /// </summary>
    /// <returns></returns>
    Task<PagedResult<TEntitySet>> GetPagedResultAsync();
    #endregion

    #region 数据操作方法
    /// <summary>
    /// 获取在更新复制属性值时需要忽略的字段配置
    /// </summary>
    /// <returns></returns>
    TypeAdapterConfig GetAdapterConfig();
    /// <summary>
    /// 新增阶段判断满足条件的数据是否存在, 存在则抛出异常, 不存在则执行基类预定义赋值操作
    /// </summary>
    /// <param name="entitySet">业务数据</param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    Task UniqueAsync(TEntitySet entitySet);
    /// <summary>
    /// 批量新增或修改数据对象模型到当前上下文, 但不提交
    /// </summary>
    /// <param name="entitySets">业务数据</param>
    /// <returns></returns>
    Task AddOrUpdateAsync(params TEntitySet[] entitySets);
    /// <summary>
    /// 单个数据对象的新增, 自动验证重复
    /// </summary>
    /// <param name="entitySet">业务数据</param>
    /// <returns></returns>
    Task<TEntitySet> AddAsync(TEntitySet entitySet);
    /// <summary>
    /// 更新阶段判断满足条件的数据是否存在, 存在则抛出异常, 不存在则执行基类预定义赋值操作
    /// </summary>
    /// <param name="entitySet">业务数据</param>
    /// <returns></returns>
    Task<TEntitySet> UpdateAsync(TEntitySet entitySet);
    /// <summary>
    /// 删除记录
    /// </summary>
    /// <param name="id">业务数据主键</param>
    /// <returns></returns>
    Task DeleteAsync(TKey id);
    #endregion
}

/// <summary>
/// 字符串作为主键的默认实现接口
/// </summary>
/// <typeparam name="TDbContext">数据库上下文</typeparam>
/// <typeparam name="TEntitySet">业务数据类型</typeparam>
public interface IDataService<TDbContext, TEntitySet> :
    IDataService<TDbContext, TEntitySet, string>
    where TDbContext : DbContext
    where TEntitySet : class, IEntitySet<string>
{ }